package com.albert.core.service.impl;

import com.albert.common.exception.Assert;
import com.albert.common.result.ResponseEnum;
import com.albert.core.enums.LendStatusEnum;
import com.albert.core.enums.TransTypeEnum;
import com.albert.core.hfb.FormHelper;
import com.albert.core.hfb.HfbConst;
import com.albert.core.hfb.RequestHelper;
import com.albert.core.mapper.LendItemMapper;
import com.albert.core.mapper.LendMapper;
import com.albert.core.mapper.UserAccountMapper;
import com.albert.core.pojo.bo.TransFlowBO;
import com.albert.core.pojo.entity.Lend;
import com.albert.core.pojo.entity.LendItem;
import com.albert.core.pojo.vo.InvestVO;
import com.albert.core.service.*;
import com.albert.core.util.LendNoUtils;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 标的出借记录表 服务实现类
 * </p>
 *
 * @author Hikari
 * @since 2024-07-21
 */
@Service
@Slf4j
public class LendItemServiceImpl extends ServiceImpl<LendItemMapper, LendItem> implements LendItemService {

    @Resource
    private LendMapper lendMapper;

    @Resource
    private LendService lendService;

    @Resource
    private UserAccountService userAccountService;

    @Resource
    private UserBindService userBindService;

    @Resource
    private TransFlowService transFlowService;

    @Resource
    private UserAccountMapper userAccountMapper;

    @Override
    public String commitInvest(InvestVO investVO) {
        //输入校验
        Long lendId = investVO.getLendId();
        //获取标的信息
        Lend lend = lendMapper.selectById(lendId);
        //标的状态必须为募集中
        Assert.isTrue(lend.getStatus().intValue()== LendStatusEnum.INVEST_RUN.getStatus().intValue(), ResponseEnum.LEND_INVEST_ERROR);
        //标的不能超卖:(已投金额+本次投资金额)>=标的金额(超卖)
        BigDecimal sum = lend.getInvestAmount().add(new BigDecimal(investVO.getInvestAmount()));
        Assert.isTrue(sum.doubleValue()<=lend.getAmount().doubleValue(), ResponseEnum.LEND_FULL_SCALE_ERROR);
        //账户可用余额充足,当前用户的余额>=当前用户的投资金额(可以投资)
        Long investUserId = investVO.getInvestUserId();
        BigDecimal account = userAccountService.getAccount(investUserId);
        Assert.isTrue(sum.doubleValue()>=Double.parseDouble(investVO.getInvestAmount()),ResponseEnum.NOT_SUFFICIENT_FUNDS_ERROR);
        //在商户平台中生成投资信息
        //标的下的投资信息
        LendItem lendItem = new LendItem();
        lendItem.setInvestUserId(investUserId);
        lendItem.setInvestName(investVO.getInvestName());
        String lendItemNo = LendNoUtils.getLendItemNo();
        lendItem.setLendItemNo(lendItemNo);
        lendItem.setInvestAmount(new BigDecimal(investVO.getInvestAmount()));
        lendItem.setLendYearRate(lend.getLendYearRate());
        lendItem.setInvestTime(LocalDateTime.now());
        lendItem.setLendStartDate(lend.getLendStartDate());
        lendItem.setLendEndDate(lend.getLendEndDate());
        //预期收益
        BigDecimal expectAmount = lendService.getInterestCount(lendItem.getInvestAmount(), lendItem.getLendYearRate(), lend.getPeriod(), lend.getReturnMethod());
        lendItem.setExpectAmount(expectAmount);
        //实际收益
        lendItem.setStatus(0);//默认状态刚刚创建
        baseMapper.insert(lendItem);
        //组装投资相关参数,提交到汇付宝托管平台
        //在托管平台同步用户的投资信息,修改用户的账户投资金额
        //获取投资人的绑定协议号
        String bindCode = userBindService.getBindCodeByUserId(investUserId);
        //获取借款人的绑定协议号
        String benefitBindCode = userBindService.getBindCodeByUserId(lend.getUserId());
        //封装提交至汇付宝的参数
        Map<String,Object> paramMap = new HashMap<>();
        paramMap.put("agentId", HfbConst.AGENT_ID);
        paramMap.put("voteBindCode",bindCode);
        paramMap.put("benefitBindCode",bindCode);
        paramMap.put("agentProjectCode",lend.getLendNo());
        paramMap.put("agentProjectName",lend.getTitle());
        //在资金托管平台的投资订单的唯一单号,要和lendItemNO保持一致
        paramMap.put("agentBillNo",lendItemNo);//订单编号
        paramMap.put("voteAmt",investVO.getInvestAmount());
        paramMap.put("votePrizeAmt","0");
        paramMap.put("voteFeeAmt","0");
        paramMap.put("projectAmt",lend.getAmount());
        paramMap.put("note","");
        paramMap.put("notifyUrl", HfbConst.INVEST_NOTIFY_URL); //检查常量是否正确
        paramMap.put("returnUrl", HfbConst.INVEST_RETURN_URL);
        paramMap.put("timestamp", RequestHelper.getTimestamp());
        String sign = RequestHelper.getSign(paramMap);
        paramMap.put("sign",sign);
        //构建自动充值自动提交表单
        String formStr = FormHelper.buildForm(HfbConst.INVEST_URL,paramMap);
        return formStr;
    }

    @Override
    public void notify(Map<String, Object> paramMap) {
        log.info("投标成功");
        //获取投资编号
        String agentBillNo = (String)paramMap.get("agentBillNo");
        boolean result = transFlowService.isSaveTransFlow(agentBillNo);
        if(result){
            log.warn("幂等性返回");
            return;
        }
        //获得用户的绑定协议号
        String bindCode = (String)paramMap.get("voteBindCode");
        String voteAmt = (String)paramMap.get("voteAmt");
        //修改商户系统中的用户账户金额,余额,冻结金额
        userAccountMapper.updateAccount(bindCode,new BigDecimal("-" + voteAmt),new BigDecimal(voteAmt));
        //修改投资记录的投资状态改已经支付
        LendItem lendItem =this.getByLendItemNo(agentBillNo);
        lendItem.setStatus(1);
        baseMapper.updateById(lendItem);
        //修改标的信息,投资人数,已投金额
        Long lendId = lendItem.getLendId();
        Lend lend = lendMapper.selectById(lendId);
        lend.setInvestAmount(lend.getInvestAmount().add(lendItem.getInvestAmount()));
        lend.setInvestNum(lend.getInvestNum()+1);
        lendMapper.updateById(lend);
        //新增交易流水
        TransFlowBO transFlowBO = new TransFlowBO(
                agentBillNo,
                bindCode,
        new BigDecimal(voteAmt),
        TransTypeEnum.INVEST_LOCK,
        "投资项目编号：" + lend.getLendNo() + "，项目名称：" + lend.getTitle());
        transFlowService.saveTransFlow(transFlowBO);
    }

    @Override
    public List<LendItem> selectByLendId(Long lendId, Integer status) {
        QueryWrapper<LendItem> queryWrapper = new QueryWrapper();
        queryWrapper.eq("lend_id", lendId);
        queryWrapper.eq("status", status);
        List<LendItem> lendItemList = baseMapper.selectList(queryWrapper);
        return lendItemList;
    }
    @Override
    public List<LendItem> selectByLendId(Long lendId) {
        QueryWrapper<LendItem> queryWrapper = new QueryWrapper();
        queryWrapper.eq("lend_id", lendId);
        List<LendItem> lendItemList = baseMapper.selectList(queryWrapper);
        return lendItemList;
    }


    public LendItem getByLendItemNo(String lendItemNo) {
        QueryWrapper<LendItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("lend_item_no", lendItemNo);
        return baseMapper.selectOne(queryWrapper);
    }
    @Override
    public LendItem selectById(Long lendItemId) {
        QueryWrapper<LendItem> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("lend_item_Id", lendItemId);
        return baseMapper.selectOne(queryWrapper);
    }
}
